import { MapInfo } from "./MapInfo";

/**
 * 寻路
 */
const {ccclass,menu, property} = cc._decorator;

@ccclass
@menu("Logic/PathFind")
export default class PathFind extends cc.Component {


 
    /**地图格子大小 */
    cellSize:number = 0;
    /**起点位置 */
    startPoint:cc.Vec2 = null;
     /**终点位置 */
    endPoint:cc.Vec2 = null;
    /**搜索出来的路径 */
    path:Array<cc.Vec2> = null; 
    /** 搜索上限 */
    findMax:number = 50000;

    mapArr = {};   
    /**地图障碍数据 */
    pathObj = {}
 
    init(mapData:MapData){
        this.mapArr = {};
        this.pathObj = mapData.cells; 
        this.cellSize = mapData.cellSize;
    }
 
    setEndNode(startPos:cc.Vec2,endPos:cc.Vec2){
        this.endPoint = endPos;
        this.startPoint = startPos; 
        console.log("起点",startPos.x,startPos.y) 
        console.log("终点",endPos.x,endPos.y)
        return this.search();
    } 
    /**
     * 开始搜索
     */
    search(){ 
        this.path = []
        //起点就是不能走的
        if (this.pathObj[this.startPoint.y + "*" + this.startPoint.x] != null)
        {
            this.path = [];
            return this.path;
        }
        this.mapArr={};
        let startNode = new MapInfo(this.startPoint.x, this.startPoint.y);
        let endNode = new MapInfo(this.endPoint.x, this.endPoint.y);
        let i, l, f,t,current,test,links;
        let openBase = Math.abs(this.startPoint.x - this.endPoint.x) + Math.abs(this.startPoint.y - this.endPoint.y);
        let open=[null,null];
        open[0] = startNode;
        startNode.version = true;
        startNode.nowCost= 0;
        let js = 0;
        while (true){
            js++;
            if (js >= this.findMax){
                //超出上限代表没找到
                this.path =[]; 
                return this.path;
            }
            current = open[0] as MapInfo;
            open[0] = current.next;
            if (open[0]!=null) open[0].pre = null;
            if (current.x == endNode.x&& current.y == endNode.y)
            {
                this.path = [];
                this.prunePath(startNode, current);
                return this.path;
            }
            if (current.links == null){
                current.addLinks(this.mapArr,this.pathObj);
            }
            links = current.links;
            l = current.linksLength;
            for (i = 0; i < l; i++){
                test = links[i];//测试的四个面
                f = current.nowCost + 1;
                if (!test.version) {
                    test.version = true;
                    test.parent = current;
                    test.nowCost = f;
                    test.dist = Math.abs(this.endPoint.x - test.x) + Math.abs(this.endPoint.y - test.y);//到终点的距离
                    f += test.dist;
                    test.mayCost = f;//估计的消耗	
                    f = (f - openBase) >> 1;
                    test.pre = null;
                    test.next = open[f];//保存下一步
                    if (open[f]!=null) open[f].pre = test;
                    open[f] = test;
                }else{
                    if (test.pre!=null) test.pre.next = test.next;
                    if (test.next!=null) test.next.pre = test.pre;
                    if (open[1] == test) open[1] = test.next;
                           
                    test.parent = current;
                    test.nowCost = f;
                    test.mayCost = f + test.dist;//加下终点绝对值
                    test.pre = null;
                    test.next = open[0];
                    if (open[0]!=null) open[0].pre = test;
                    open[0] = test;
                }
            }
            if (open[0]==null)
            {
                if (open[1] == null){ 
                    break;
                } 
                t = open[0];
                open[0] = open[1];
                open[1] = t;
                openBase += 2;
            }
        }  
    }

    prunePath(startNode, endNode){
        if (this.startPoint.x == this.endPoint.x&&this.startPoint.y==this.endPoint.y) return;
        let current = endNode;
        this.path.push(current);
        while (current.parent) {
            if (current.x == startNode.x&& current.y == startNode.y){
                this.path[this.path.length]=cc.v2(current.x,current.y); 
                return;
            }
            current = current.parent;
            this.path.push(current);
        }  
    }

  
}
